;; midi/midi-port.scm - (c) rohan drape, 2002-2005

;; Read a midi event from `port', the event is returned as value of
;; type <u8vector>.

(define (midi-event-read port)
  (define make-result 
    (lambda args (list->u8vector args)))
  (let ((b (read-byte port)))
    (if (eof-object? b)
	b
	(if (not (= 0 (bitwise-and #x80 b)))
	    (let ((status-major (bitwise-and b #xF0)))
	      (case status-major 
		((MC-program-change 
		  MC-channel-aftertouch)
		 (make-result b (read-byte port)))
		((MC-note-off 
		  MC-note-on 
		  MC-poly-aftertouch 
		  MC-control-change 
		  MC-pitch-wheel)
		 (make-result b (read-byte port) (read-byte port)))
		((MC-system-message)
		 (let ((status-minor (bitwise-and b #x0F)))
		   (case status-minor
		     ;; System Exclusive messages are discarded, they
		     ;; should not be.
		     ((MC-system-exclusive)
		      (do ((t (read-byte port) (read-byte port)))
			  ((= t #xF7))
			(if (eof-object? t) 
			    (error "End of data in System Exclusive"))))
		     ((MC-tune-request 
		       MC-midi-clock 
		       MC-midi-start 
		       MC-midi-continue 
		       MC-midi-stop 
		       MC-active-sense)
		      (make-result b))
		     ((MC-mtc-quarter-frame 
		       MC-song-select 
		       MC-midi-tick)
		      (make-result b (read-byte port)))
		     ((MC-song-position-pointer)
		      (make-result b (read-byte port) (read-byte port)))
		     (else
		      (inform "Unknown Non-Voice Message:" status-minor)))))
		(else
		 (inform "Non status byte:" b))))))))

;; Write the midi event at the <u8vector> `data' to `port'.  

(define (midi-event-write data port)
  (write-u8vector data port))
